
import { newGroup } from "../cluster";

import { GroupWorkers } from "../../terminal/workers";
import { mapRoomDomain } from "../../../../global/map";
import { ClusterDefenders } from "../defenders";
import { ClusterExplorers } from "../explorers";
import { errLog } from "../../../../util/log";
import { getCreepCountCoeficient, getMaxEnergy, getMinEnergy } from "../../../../role/spawn";
import { ClusterStructure } from "../structure";
import { ClusterColony, structureClusterTemplates } from "./colony";
import { ClusterCore } from "../core";

export class ClusterIndependent extends ClusterColony{
    get structureClusterList(){
        return [structureClusterTemplates.core];
    }
    get maxSize(){
        let ans = 0;
        ans+=this.workerGroup.maxSize;
        if(this.isPanicing()){
            ans+=this.defenderGroup.maxSize;
        }else{
            ans++;
        }
        ans+=this.explorerGroup.maxSize;
        return ans;
    }
    get size(){
        return this.workerGroup.size+this.defenderGroup.size+this.explorerGroup.size;
    }
    /**
     * 
     * @param {Room} spawnRoom 
     */
    init(spawnRoom){
        super.init(spawnRoom);
        mapRoomDomain(spawnRoom);
        this.workerGroup = new GroupWorkers(spawnRoom);
        this.defenderGroup = new ClusterDefenders(spawnRoom);
        this.explorerGroup = new ClusterExplorers(spawnRoom);
        this.structureGroup = new ClusterStructure(spawnRoom);
        this.core = new ClusterCore(spawnRoom, undefined);
    }
    serialize(){
        return {
            super: super.serialize(), 
            workerGroup: this.workerGroup.serialize(),
            defenderGroup: this.defenderGroup.serialize(),
            explorerGroup: this.explorerGroup.serialize(),
            structureGroup: this.structureGroup.serialize(),
            core: this.core.serialize(),
        };
    }
    deserialize(obj){
        super.deserialize(obj.super);
        this.workerGroup = newGroup(GroupWorkers, obj.workerGroup, this.spawnRoom);
        this.defenderGroup = newGroup(ClusterDefenders, obj.defenderGroup, this.spawnRoom);
        this.explorerGroup = newGroup(ClusterExplorers, obj.explorerGroup, this.spawnRoom);
        this.structureGroup = newGroup(ClusterStructure, obj.structureGroup, this.spawnRoom);
        this.core = newGroup(ClusterCore, obj.core, this.spawnRoom);
        this.spawnRoom.maxCreepCount = this.maxSize;
        return this;
    }
    isPanicing(){
        return this.defenderGroup.targets.length > 0;
    }
    normalSpawn(){
        if(this.workerGroup.size < 3){
            return this.workerGroup.spawn();
        }

        if(this.core.isActive() && this.core.size<this.core.maxSize){
            return this.core.spawn();
        }

        if(this.workerGroup.size/this.workerGroup.maxSize<0.3){
            return this.workerGroup.spawn();
        }
        if(getMinEnergy(this.spawnRoom)/getMaxEnergy(this.spawnRoom)>0.5 && this.explorerGroup.size<this.explorerGroup.maxSize){
            let ret = this.explorerGroup.spawn();
            if(ret === OK){
                return ret;
            }
        }


        if(this.workerGroup.size/this.workerGroup.maxSize<0.75){
            return this.workerGroup.spawn();
        }
        // console.log('def');
        if(this.defenderGroup.size === 0 && getCreepCountCoeficient(this.spawnRoom, false)>0.9){
            return this.defenderGroup.spawn();
        }
        // console.log('worker max');
        if(this.workerGroup.size<this.workerGroup.maxSize){
            return this.workerGroup.spawn();
        }
        // console.log('exp max');
        if(this.explorerGroup.size<this.explorerGroup.maxSize){
            if(this.explorerGroup.spawn() === OK){
                return OK;
            }
        }
        // console.log('full');
        return ERR_FULL;
    }
    panicSpawn(){
        // console.log('panic')
        if(this.defenderGroup.size === 0){
            return this.defenderGroup.spawn();
        }
        if(this.workerGroup.size/this.workerGroup.maxSize<0.4){
            return this.workerGroup.spawn();
        }

        if(this.defenderGroup.size/this.defenderGroup.maxSize<this.workerGroup.size/this.workerGroup.maxSize){
            return this.defenderGroup.spawn();
        }

        if(this.core.isActive() && this.core.size<this.core.maxSize){
            return this.core.spawn();
        }

        if(this.workerGroup.size<this.workerGroup.maxSize){
            return this.workerGroup.spawn();
        }
        if(this.explorerGroup.size<this.explorerGroup.maxSize){
            return this.explorerGroup.spawn();
        }
        if(this.defenderGroup.size<this.defenderGroup.maxSize){
            return this.defenderGroup.spawn();
        }

        return ERR_FULL;
    }
    spawn(){
        if(this.isPanicing()){
            return this.panicSpawn();
        }
        return this.normalSpawn();
    }
    run(){
        try{
            super.run();
        }catch(e){
            errLog(e);
        }

        if(this.structurePos && this.structurePos[0] && !this.core.isActive()){
            let {x,y} = this.structurePos[0];
            this.core.corePos = new RoomPosition(x,y,this.spawnRoomName);
        }

        try{
            this.explorerGroup.run();
        }catch(e){
            errLog(e);
        }
        try{
            this.defenderGroup.run();
        }catch(e){
            errLog(e);
        }
        try{
            this.workerGroup.run();
        }catch(e){
            errLog(e);
        }

        try{
            this.structureGroup.run(this.map);
        }catch(e){
            errLog(e);
        }

        try{
            this.core.run();
        }catch(e){
            errLog(e);
        }

        return OK;
    }
    
}